package com.ruoyi.framework.web.exception

import com.ruoyi.common.constant.*
import com.ruoyi.common.exception.DemoModeException
import com.ruoyi.common.exception.ServiceException
import com.ruoyi.common.utils.*
import com.ruoyi.framework.web.domain.AjaxResult
import com.ruoyi.framework.web.exception.GlobalExceptionHandler
import org.slf4j.LoggerFactory
import org.springframework.security.access.AccessDeniedException
import org.springframework.validation.BindException
import org.springframework.web.HttpRequestMethodNotSupportedException
import org.springframework.web.bind.MethodArgumentNotValidException
import org.springframework.web.bind.annotation.*
import javax.servlet.http.HttpServletRequest

/**
 * 全局异常处理器
 *
 * @author ruoyi
 */
@RestControllerAdvice
class GlobalExceptionHandler {
    companion object {
        private val log = LoggerFactory.getLogger(GlobalExceptionHandler::class.java)
    }
    /**
     * 权限校验异常
     */
    @ExceptionHandler(AccessDeniedException::class)
    fun handleAccessDeniedException(e: AccessDeniedException, request: HttpServletRequest): AjaxResult {
        val requestURI = request.requestURI
        log.error("请求地址'{}',权限校验失败'{}'", requestURI, e.message)
        return AjaxResult.error(HttpStatus.FORBIDDEN, "没有权限，请联系管理员授权")
    }

    /**
     * 请求方式不支持
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException::class)
    fun handleHttpRequestMethodNotSupported(
        e: HttpRequestMethodNotSupportedException,
        request: HttpServletRequest
    ): AjaxResult {
        val requestURI = request.requestURI
        log.error("请求地址'{}',不支持'{}'请求", requestURI, e.method)
        return AjaxResult.error(e.message)
    }

    /**
     * 业务异常
     */
    @ExceptionHandler(ServiceException::class)
    fun handleServiceException(e: ServiceException, request: HttpServletRequest?): AjaxResult {
        log.error(e.message, e)
        val code = e.code
        return if (StringUtils.isNotNull(code)) AjaxResult.error(
            code!!,
            e.message
        ) else AjaxResult.error(e.message)
    }

    /**
     * 拦截未知的运行时异常
     */
    @ExceptionHandler(RuntimeException::class)
    fun handleRuntimeException(e: RuntimeException, request: HttpServletRequest): AjaxResult {
        val requestURI = request.requestURI
        log.error("请求地址'{}',发生未知异常.", requestURI, e)
        return AjaxResult.error(e.message)
    }

    /**
     * 系统异常
     */
    @ExceptionHandler(Exception::class)
    fun handleException(e: Exception, request: HttpServletRequest): AjaxResult {
        val requestURI = request.requestURI
        log.error("请求地址'{}',发生系统异常.", requestURI, e)
        return AjaxResult.error(e.message)
    }

    /**
     * 自定义验证异常
     */
    @ExceptionHandler(BindException::class)
    fun handleBindException(e: BindException): AjaxResult {
        log.error(e.message, e)
        val message = e.allErrors[0].defaultMessage
        return AjaxResult.error(message)
    }

    /**
     * 自定义验证异常
     */
    @ExceptionHandler(MethodArgumentNotValidException::class)
    fun handleMethodArgumentNotValidException(e: MethodArgumentNotValidException): Any {
        log.error(e.message, e)
        val message = e.bindingResult.fieldError?.defaultMessage
        return AjaxResult.error(message)
    }

    /**
     * 演示模式异常
     */
    @ExceptionHandler(DemoModeException::class)
    fun handleDemoModeException(e: DemoModeException?): AjaxResult {
        return AjaxResult.error("演示模式，不允许操作")
    }

}
